#pragma once

#include "log.hpp"
#include "Inet_Addr.hpp"
#include "threadpool.hpp"
#include "LockGuard.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <sys/socket.h>
#include <functional>

using thread_task_t = std::function<void()>;

ThreadPool<thread_task_t> tp(3);

class massageRoute
{
private:
    // 判断用户是否存在
    bool isExist(const InetAddr &addr)
    {
        auto iter = _addr.begin();
        while (iter != _addr.end())
        {
            if (*iter == addr)
                return true;

            iter++;
        }

        return false;
    }

    void addAddr(InetAddr &addr)
    {
        if (!isExist(addr))
        {
            _addr.push_back(addr);
            LOG(INFO, "addr [%s:%d] add success", addr.IP().c_str(), addr.Port());
        }
    }

    void deleteAddr(InetAddr &addr)
    {
        auto iter = _addr.begin();
        while (iter != _addr.end())
        {
            if (*iter == addr)
            {
                _addr.erase(iter);
                LOG(INFO, "addr [%s:%d] delete success", addr.IP().c_str(), addr.Port());
                return;
            }

            iter++;
        }
    }

    void routeHandler(int sockfd, const std::string massage, InetAddr client_addr)
    {
        LockGuard lock(_mutex);
        std::string route_massage = "[" + client_addr.IP() + ":" + std::to_string(client_addr.Port()) + "]: " + massage;

        // 转发消息
        for (auto client : _addr)
        {
            struct sockaddr_in addr = client.Addr();
            int n = sendto(sockfd, route_massage.c_str(), sizeof(route_massage), 0, (struct sockaddr *)&addr, sizeof(addr));
        }
    }

public:
    massageRoute()
    {
        pthread_mutex_init(&_mutex, nullptr);
        tp.threadInit();
        tp.threadStart();
    }
    // 将消息转发给所有client
    void route(int sockfd, const std::string massage, InetAddr client_addr)
    {
        // 如果是新client，就将client信息放入数组
        addAddr(client_addr);

        // 关闭client
        if (massage == "Q" || massage == "quit" || massage == "q" || massage == "QUIT")
            deleteAddr(client_addr);

        //利用线程池转发消息
        thread_task_t task = std::bind(&massageRoute::routeHandler, this, sockfd, massage, client_addr);
        tp.enQueue(task);
    }

private:
    std::vector<InetAddr> _addr; // 用于记录所有client的socket信息（IP + Port）
    pthread_mutex_t _mutex;
};
